package cn.jnetty.remoting.udp;

import cn.jnetty.api.JnettyProperties;
import cn.jnetty.api.JnettyHandler;
import cn.jnetty.api.JnettyServer;
import cn.jnetty.api.annotation.JAutowired;
import cn.jnetty.api.annotation.JComponent;
import cn.jnetty.remoting.tcp.JnettyTcpSimpleChannelInboundHandlerImpl;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @author 猪哥亮
 * @email 1030681978@qq.com
 * @date 2020/4/2 18:39
 * 描述：
 */
@JComponent
public class JnettyUdpServer implements JnettyServer {
    private EventLoopGroup bossGroup;
    private final Logger log = LoggerFactory.getLogger(JnettyUdpServer.class);
    @JAutowired(required = false)
    private JnettyHandler handler;
    @JAutowired(required = false)
    private JnettyProperties configuration;
    public JnettyUdpServer() {
    }

    @Override
    public void init() {
        this.bossGroup = new NioEventLoopGroup();
    }

    @Override
    public void startup() {
        try
        {
            //通过NioDatagramChannel创建Channel，并设置Socket参数支持广播
            //UDP相对于TCP不需要在客户端和服务端建立实际的连接，因此不需要为连接（ChannelPipeline）设置handler
            Bootstrap b=new Bootstrap();
            b.group(bossGroup)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(new JnettyTcpSimpleChannelInboundHandlerImpl(handler));
            if (configuration.getUdpPort() <= 0) {
                log.info("jnetty-udp-服務器启动失败，绑定的端口号不能为0。");
                throw new RuntimeException("jnetty-udp-服務器启动失败，绑定的端口号不能为0。");
            }
            log.info("jnetty-udp-服务器启动，绑定端口####################" +  configuration.getUdpPort());
            b.bind(configuration.getUdpPort()).sync();
            log.info("jnetty-udp-服务器启动成功.端口綁定>>>>>>>>>>>>" + configuration.getUdpPort());
        }
        catch (Exception e)
        {
            throw new RuntimeException("jnetty-udp-目标端口已被占用 port=" + configuration.getUdpPort(), e);
        }

    }
    public static final int SHUTDOWN_MAX_TIME = 1;
    @Override
    public void shutdown() {
        Future<?> boosFuture = bossGroup.shutdownGracefully();
        try {
            if (boosFuture.await(SHUTDOWN_MAX_TIME, TimeUnit.MINUTES)) {
                log.info("jnetty-udp-NettyBoss关闭成功.");
            }
        } catch (InterruptedException ie) {
            log.error("jnetty-udp-关闭网络时发生异常.",ie);
        }
    }
}
